<?php
declare(strict_types=1);


namespace app\result;

use app\model\CodeLog;
use app\model\extend\PCashbook;
use app\model\user\Cashflows;
use app\model\user\User;
use app\model\user\UserLoginLog;
use app\model\user\UserMsg;
use app\result\extend\CashbookResult;

class UserResult extends BaseResult
{
    public function __construct()
    {
        $this->model = new User();
        parent::__construct();
        $this->cancel_account();
    }

    //开始注销
    private function cancel_account()
    {
        //每5分钟
        $ckey = 'cancel_account_check';
        if (cache($ckey)) {
            return;
        }
        cache($ckey, 1, 300);
        $users = $this->model->data_list_nopage([['cancel_expire', 'between', [1, time() - 1]]], 'user_id,cancel_expire');
        if ($users) {
            foreach ($users as $user) {
                $user_id = $user['user_id'];
                //删除账号
                (new User())->where('user_id', '=', $user_id)->delete();
            }
        }
    }

    /**
     * 获取用户列表
     * @return array
     */
    public function list($args = [])
    {
        $page = request()->param('page', 1, 'intval');
        $pageSize = request()->param('limit', 10, 'intval');
        $sort = request()->param('sort', '', 'trim');
        $cancel_expire = intval($args['cancel_expire'] ?? 0);
        $active_time = $args['active_time'] ?? [];
        $where = [];
        if (!empty($args['keyword'])) {
            $where[] = ['username|account|user_id|email|remark', 'like', '%' . trim($args['keyword']) . '%'];
        }
        if ($cancel_expire) {
            $where[] = ['cancel_expire', '>', 0];
        }
        if ($active_time) {
            $where[] = ['last_active_time', 'between', $active_time];
        }
        $orderBy = 'user_id desc';
        if ($sort == 'created_at') {
            $orderBy = 'created_at asc';
        } elseif ($sort == 'last_login_time') {
            $orderBy = 'last_login_time desc';
        } elseif ($sort == 'updated_at') {
            $orderBy = 'updated_at DESC';
        } elseif ($sort == 'last_active_at') {
            $orderBy = 'last_active_time DESC';
        } elseif ($sort == 'bill_count') {
            $orderBy = 'all_bill_count DESC';
        }
        $total = $this->model->data_count($where);
        $data = $this->model->data_list($where, '*', $orderBy, $page, $pageSize);
        if ($data) {
            foreach ($data as &$v) {
                $v['cash_count'] = $v['all_bill_count'];
                $v['last_active_platform'] = ($v['last_active_platform'] ?: 'unknown');
                if ($v['last_active_version']) {
                    $v['last_active_platform'] = $v['last_active_platform'] . '-' . $v['last_active_version'];
                }
                if ($v['cancel_expire']) {
                    $v['cancel_expire'] = date('Y-m-d H:i:s', $v['cancel_expire']);
                }
            }
            unset($v);
        }
        return $this->success_return('success', [
            'total' => $total,
            'list' => $data
        ]);
    }

    /**
     * 获取指定用户信息
     * @param int $user_code 用户user_code
     * @return array
     */
    public function get(int $user_code): array
    {
        $user = (new User())->data_get(['user_code' => $user_code]);
        return self::success_return('success', $user);
    }

    public function save($args = [])
    {
        $user_id = intval($args['user_id']);
        $password = $args['password'] ?? '';
        $remark = $args['remark'] ?? '';
        if (!$user_id) {
            return $this->error_return('请选择需要修改的用户');
        }
        if (!$password && !$remark) {
            return $this->error_return('请输入修改内容');
        }
        $update_data = [];
        if ($password) {
            $salt = substr(md5(uniqid('', true)), 0, 10);
            $password = md5($args['password'] . $salt);
            $update_data['password'] = $password;
            $update_data['salt'] = $salt;
        }
        if ($remark) {
            $update_data['remark'] = $remark;
        }
        $user = $this->model->data_update(['user_id' => $user_id], $update_data);
        return $this->success_return('success', $user);
    }

    //更新最后活跃时间
    public function update_last_active_time($user_id, $data)
    {
        return $this->model->data_update(['user_id' => $user_id], $data);
    }


    //通过邀请码查询用户
    public function get_info_by_code($user_code): array
    {
        $model = new User();

        $user = $model->data_get(['user_code' => $user_code], 'account,user_id,email,avatar,username as nick_name,user_code,cancel_expire,created_at,all_bill_count');
        if (!$user) {
            return $this->error_return('用户不存在');
        }
        $user = $user->toArray();
        if (!empty($user['cancel_expire'])) {
            $user['cancel_expire'] = date('Y-m-d H:i:s', $user['cancel_expire']);
        }
        $default_cashbook = (new CashbookResult())->get_default_cashbook($user['user_id']);
        $user['default_cashbook'] = [
            'id' => $default_cashbook['cashbook_id'] ?? 0,
            'name' => $default_cashbook['name'] ?? '默认账本',
        ];
        $user['unread_count'] = (new UserMsg())->data_count(['user_id' => $user['user_id'], 'read_time' => 0]);//未读消息数
        $user['sign_in_day'] = intval((strtotime('tomorrow') - 1 - strtotime(date('Y-m-d', strtotime($user['created_at'])))) / 86400);//使用天数
        $user['all_bill_day'] = (new Cashflows())->data_count(['user_id' => $user['user_id']], 'id', 'date');//总记账天数

        if (empty($user['avatar'])) {
            $user['avatar'] = request()->domain(true) . '/static/image/default_image.png';
        }
        //广告控制
        $user['position'] = [
            'user_center' => false,//个人中心
            'setting_page' => false,//设置页
            'msg_info_page' => false,//消息页
            'statistics_page' => false,//统计页
        ];
        //自己的账号
        if (in_array($user['user_id'], [88909, 88923, 88925])) {
            //广告全开
            array_walk($user['position'], function (&$v, $k) {
                $v = true;
            });
        }

        return $this->success_return('success', $user);
    }

    public function get_user_code()
    {
        //生成8位数,纯数字邀请码
        $todayRegCount = (new User())->data_count([['created_at', '>=', date('Y-m-d 00:00:00')]], 'user_id');
        $utr = $todayRegCount + 1;
        //不足2位，补0
        $utr = str_pad(strval($utr), 2, '0', STR_PAD_LEFT);

        $user_code = '1' . $utr . rand(10000, 99999);
        //去重
        while (true) {
            $user_code_user = $this->model->get_value(['user_code' => $user_code], 'user_id');
            if (!$user_code_user) {
                break;
            }
            $user_code = '1' . $utr . rand(10000, 99999);
        }
        return $user_code;
    }

    //获取昵称
    public function getNickname(): string
    {
        $adjectives = ['梦幻', '星辰', '夜色', '晨曦', '幽静', '灵动', '炽烈', '温柔', '神秘', '璀璨',
            '皎洁', '绚烂', '飘逸', '清冷', '优雅', '深邃', '宁静', '温暖', '逍遥', '浩瀚', '清风',
            '空灵', '婉约', '磅礴', '静谧', '绚彩', '流光', '逸致', '清幽', '高远', '苍茫',
            '绮丽', '悠然', '潋滟', '澄澈', '芳馨', '馥郁', '玄妙', '超凡', '脱俗', '恬淡',
            '素雅', '婀娜', '巍峨', '浩渺', '斑斓', '柔和', '寂寥', '明快', '纯净', '古朴'];
        $nouns = ['飞鸟', '流云', '微风', '细雨', '繁花', '明月', '清泉', '远山', '暮雪', '流星',
            '苍穹', '碧海', '红叶', '紫霞', '青松', '白雪', '金阳', '银霜', '丹心', '墨竹', '松花',
            '飞鸿', '晨露', '晚霞', '秋水', '寒梅', '春草', '夏荷', '冬柏', '玉兔', '金乌',
            '瑶池', '翠柳', '绿萝', '黄鹂', '紫藤', '青鸾', '白鹭', '红枫', '墨菊', '锦鲤',
            '幽兰', '瑞雪', '祥云', '碧波', '银河', '瀑布', '彩虹', '草原', '沙漠', '森林'];
        $connectors = ['之', '与', '于', '若', '如', '', '-', '·'];
        $adjectiveKey = array_rand($adjectives);
        $nounKey = array_rand($nouns);
        $connectorKey = array_rand($connectors);
        return $adjectives[$adjectiveKey] . $connectors[$connectorKey] . $nouns[$nounKey];
    }

    //注册
    public function register($args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['account'] ?? "");
        $password = trim($args['password'] ?? '');
        $password1 = trim($args['password1'] ?? '');
        $captcha_code = trim($args['captcha_code'] ?? "");
        $captcha_key = trim($args['captcha_key'] ?? "");
        if (empty($account)) {
            return $this->error_return('请输入账号', $args);
        }
        if (empty($password)) {
            return $this->error_return('请输入密码');
        }
        if ($password != $password1) {
            return $this->error_return('两次密码不一致');
        }
        if (empty($captcha_code) || empty($captcha_key)) {
            return $this->error_return('验证码不能为空');
        }

        if (!(new CodeResult())->captcha_check($captcha_key, $captcha_code)) {
            return $this->error_return('验证码错误');
        }
        if (strlen($account) < 3) {
            return $this->error_return('账号长度不能小于3位');
        }

        //判断密码不可以小于6位，大于16位
        if (strlen($args['password']) < 6 || strlen($args['password']) > 16) {
            return $this->error_return('密码长度为6-16位');
        }
        //密码只能是数字、字母、下划线
        if (!preg_match('/^[0-9a-zA-Z_]+$/', $args['password'])) {
            return $this->error_return('密码只能是数字、字母、下划线');
        }

        $args['password'] = trim($args['password']);
        $user_code = $this->get_user_code();
        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($args['password'] . $salt);
        if (empty($args['username'])) {
            //截取手机号后面4位
            $args['username'] = $this->getNickname();
        }
        $user = $this->model->data_get(['account' => $account], 'user_id');
        if ($user) {
            return $this->error_return('账号已存在');
        }
        //判断是不是email
        if (filter_var($account, FILTER_VALIDATE_EMAIL)) {
            $args['email'] = $account;
            if ($this->model->data_get(['email' => $account])) {
                return $this->error_return('邮箱已存在');
            }
        }

        $baseData = [
            'avatar' => request()->domain(true) . '/static/image/default_image.png',
            'username' => $args['username'],
            'account' => $account,
            'password' => $password,
            'salt' => $salt,
            'user_code' => $user_code,
        ];

        $user_id = (new User())->data_add($baseData);
        if (!$user_id) {
            return $this->error_return('注册失败');
        }
        (new UserMsgResult())->add($user_id, [
            'title' => '注册成功，请记录账号',
            'content' => '系统已为您创建了账号：<b style="color:red">' . $account . '</b>，登录后即可开始使用。如需要修改账号关联数据，请通过【设置》安全中心》账号修改】进行修改为自己想要的账号。<br/> .app或者H5（<a href="https://jz.api.alipay168.cn">随手记</a>）操作。',
            'type' => 1,
            'path_info' => [
                'title' => '安全中心',
                'path' => '/pages/setting/safe/index',
                'jump_type' => 'inner',//inner=内页，tab=底部导航，link=外链
            ],
        ]);
        return $this->success_return('注册成功', ['user_code' => $user_code]);
    }

    //登录
    public function pwd_login($args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['account'] ?? "");
        $password = trim($args['password'] ?? '');
        $captcha_code = trim($args['captcha_code'] ?? "");
        $captcha_key = trim($args['captcha_key'] ?? "");
        if (empty($account)) {
            return $this->error_return('登录账号不能为空');
        }
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        if (empty($captcha_code) || empty($captcha_key)) {
            return $this->error_return('验证码不能为空');
        }

        if (!(new CodeResult())->captcha_check($captcha_key, $captcha_code)) {
            return $this->error_return('验证码错误');
        }


        $user = $this->model->data_get(['account' => $account], 'user_id,password,salt,user_code');
        if (!$user) {
            $user = $this->model->data_get(['email' => $account], 'user_id,password,salt,user_code');
            if (!$user) {
                return $this->error_return('账号未注册');
            }
        }
        $up = [];

        if (md5($password . $user['salt']) != $user['password']) {
            return $this->error_return('密码错误');
        }
        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($password . $salt);
        $up = array_merge($up, [
            'password' => $password,
            'salt' => $salt,
        ]);
        $res = $this->add_user_log($user['user_id'], 1, $up);
        if (!$res) {
            return $this->error_return('登录失败');
        }
        //初始化分类
        CategoryResult::init($user['user_id']);
        $token = $this->set_token($user['user_code']);
        return $this->success_return('登录成功', ['token' => $token]);
    }

    public function wx_login($args)
    {
        $code = $args['code'] ?? '';
        $platform = $args['platform'] ?? '';//wx/qq/tt
        $res = $this->get_openid($code, $platform);

        if ($res['code'] <> 0) {
            return $this->error_return($res['msg']);
        }
        $wxxcx_openid = $res['data']['openid'];
        $unionid = $res['data']['unionid'] ?? '';
        if (empty($unionid) && empty($wxxcx_openid)) {
            return $this->error_return('登录失败');
        }
        if (!empty($unionid)) {
            $user = $this->model->data_get(['unionid' => $unionid], 'user_id,password,salt,user_code');
        } else {
            $user = $this->model->data_get(['wxxcx_openid' => $wxxcx_openid], 'user_id,password,salt,user_code');
        }

        if (!$user) {
            $user_code = $this->get_user_code();
            $salt = substr(md5(uniqid('', true)), 0, 10);
            $pwd = rand(1000000, 9999999);
            $baseData = [
                'avatar' => request()->domain(true) . '/static/image/default_image.png',
                'username' => $this->getNickname(),
                'account' => $user_code,
                'password' => md5($pwd . $salt),
                'salt' => $salt,
                'user_code' => $user_code,
                'wxxcx_openid' => $wxxcx_openid,
                'unionid' => $unionid
            ];
            $user_id = (new User())->data_add($baseData);
            if (!$user_id) {
                return $this->error_return('登录失败');
            }
            (new UserMsgResult())->add($user_id, [
                'title' => '微信登录成功',
                'content' => '这是您第一次使用微信登录，系统已为您创建了账号：<b style="color:red">' . $user_code . '</b>，初始密码为：<b style="color:red">' . $pwd . '</b>，请及时修改密码，在h5和app账号通用，忘记初始密码可以通过小程序登录后查看本消息。如需要修改账号关联数据，请通过app或者H5（<a href="http://jz.alipay168.cn">随手记</a>）操作。',
                'type' => 1,
                'path_info' => [
                    'title' => '安全中心',
                    'path' => '/pages/setting/safe/index',
                    'jump_type' => 'inner',//inner=内页，tab=底部导航，link=外链
                ],
            ]);
            $user = $this->model->data_get(['user_id' => $user_id], 'user_id,password,salt,user_code');

        }

        $res = $this->add_user_log($user['user_id'], 3, []);
        if (!$res) {
            return $this->error_return('登录失败');
        }
        //初始化分类
        CategoryResult::init($user['user_id']);
        $token = $this->set_token($user['user_code']);
        return $this->success_return('登录成功', ['token' => $token]);
    }

    //微信小程序通过code获取openid
    public function get_openid($code, $platform)
    {
        $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . config('wx.appid') . "&secret=" . config('wx.secret') . "&js_code=" . $code . "&grant_type=authorization_code";
        $res = json_decode(bs_curl_get($url), true);
        if (isset($res['errcode'])) {
            return $this->error_return('获取openid失败', $res);
        }
        return self::success_return('获取openid成功', $res);
    }

    public function code_login($phone, $code): array
    {
        if (empty($phone)) {
            return $this->error_return('手机号不能为空');
        }
        if (empty($code)) {
            return $this->error_return('验证码不能为空');
        }
        $check_code = (new CodeResult())->check_code($phone, $code);
        if ($check_code['status'] != 0) {
            return $check_code;
        }
        $user = $this->model->data_get(['phone' => $phone], 'user_id,user_code');
        if (!$user) {
            return $this->error_return('账号未注册');
        }
        $res = $this->add_user_log($user['user_id'], 2);
        if (!$res) {
            return $this->error_return('登录失败');
        }
        $token = $this->set_token($user['user_code']);
        return $this->success_return('登录成功', ['token' => $token]);
    }

    public static function logout($token)
    {
        if ($token) {
            $token_cache = 'user_token_' . md5($token);
            cache($token_cache, 1, 86400 * 7);
        }
        return self::success_return('退出成功');
    }

    //设置token
    private function set_token($user_code)
    {
        $payload = [
            "iss" => request()->domain(), // 使用当前请求域名作为签发者
            "aud" => request()->domain(), // 使用当前请求域名作为受众
            "iat" => time(), // 当前时间戳作为签发时间
            "nbf" => time(), // 0秒后生效
            "exp" => time() + 86400 * 60, // 有效期
            "sub" => $user_code, // 用户代码作为主题
            "jti" => uniqid('', true), // 唯一的JWT ID
        ];

        $service = new JWTResult();
        return $service->encode($payload);
    }


    //获取token用户信息
    public function get_token_user($token, $field = '*')
    {
        if (cache('user_token_' . md5($token))) {
            return self::error_return('token已过期');
        }
        if (strlen($token) === 32) {
            //老用户兼容
            $user_code = cache($token);
            if (!$user_code) {
                return self::error_return('token已过期');
            }
            return (new User())->data_get(['user_code' => $user_code], $field);
        }
        try {
            $decode = (new JWTResult())->decode($token);
        } catch (\Exception $e) {
            bs_log($e->getMessage(), 'decode', 'jwt_decode_error.log');
            return self::error_return('token已过期', $e->getMessage());
        };

        if (isset($decoded->exp) && $decoded->exp < time()) {
            return self::error_return('token已过期');
        }

        // 检查'nbf'声明以确认当前时间是否在令牌生效之前
        if (isset($decoded->nbf) && $decoded->nbf > time()) {
            return self::error_return('token未生效，请等待一段时间再试');
        }

        $user_code = $decode->sub;
        if (!$user_code) {
            return self::error_return('token已过期');
        }
        return self::success_return('success', (new User())->data_get(['user_code' => $user_code], $field));
    }

    //更新登录信息
    private function add_user_log($user_id, $type, $update_data = [])
    {
        $update_data = array_merge($update_data, [
            'last_login_ip' => request()->ip(),
            'last_login_time' => date('Y-m-d H:i:s'),
        ]);
        (new UserLoginLog())->data_add([
            'user_id' => $user_id,
            'type' => $type,//1=密码，2=短信
            'login_ip' => request()->ip(),
        ]);
        return (new User())->data_update(['user_id' => $user_id], $update_data);
    }

    //更新基本信息
    public function update_info($user_id, $data): array
    {
        if (!request()->isPut()) {
            return $this->error_return('非法请求');
        }
        if (!empty($data['nick_name']) && mb_strlen($data['nick_name']) > 10) {
            return $this->error_return('昵称长度不能超过10个字符');
        }
        $up = [];
        if (!empty($data['avatar'])) {
            $up['avatar'] = $data['avatar'];

        }
        if (!empty($data['nick_name'])) {
            $up['username'] = $data['nick_name'];
        }
        (new User())->data_update(['user_id' => $user_id], $up);
        return $this->success_return('更新成功');
    }

    //修改账号
    public function update_account($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = $args['account'] ?? '';
        $password = $args['password'] ?? '';
        if (empty($account)) {
            return $this->error_return('账号不能为空');
        } elseif (mb_strlen($account) > 40) {
            return $this->error_return('账号不能超过40个字符');
        }
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }

        $user = (new User())->data_get(['account' => $account], 'user_id');
        if ($user && $user['user_id'] != $user_id) {
            return $this->error_return('账号已存在');
        }
        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password');
        if ($account == $myInfo['account']) {
            return $this->error_return('账号未修改');
        }
        if ($myInfo['account_edit_time'] + 86400 * 30 > time()) {
            return $this->error_return('30天内只能修改一次，还有' . intval(($myInfo['account_edit_time'] + 86400 * 30 - time()) / 86400) . '天可修改');
        }
        if (md5($password . $myInfo['salt']) <> $myInfo['password']) {
            return $this->error_return('密码错误');
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['account' => $account, 'account_edit_time' => time()]);
        UserMsgResult::add($user_id, [
            'title' => '账号修改通知',
            'content' => '账号已修改为：<b style="color:red">' . $account . '</b>，请使用新账号进行登录。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('修改失败');
    }

    //注销账号
    public function account_cancel($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $password = $args['password'] ?? '';

        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password,cancel_expire');
        if (!empty($myInfo['cancel_expire'])) {
            return $this->error_return('账号已申请注销，请于' . date('Y-m-d H:i:s', $myInfo['cancel_expire']) . '后可重新注册');
        }

        if (md5($password . $myInfo['salt']) <> $myInfo['password']) {
            return $this->error_return('密码错误');
        }
        $expire = time() + 86400 * 7;
        $res = (new User())->data_update(['user_id' => $user_id], ['cancel_expire' => $expire]);
        UserMsgResult::add($user_id, [
            'title' => '注销账号通知',
            'content' => '账号：<b style="color:red">' . $myInfo['account'] . '</b>已经申请注销，7天后将彻底注销，如果想取消注销，请于' . date('Y-m-d H:i:s', $expire) . '前登录账号并到注销页面取消注销。',
            'type' => 1
        ]);
        return $res ? $this->success_return('操作成功') : $this->error_return('操作失败');
    }

    //取消注销
    public function regret_cancel($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $password = $args['password'] ?? '';

        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password,cancel_expire');
        if (empty($myInfo['cancel_expire'])) {
            return $this->error_return('账号没有申请注销');
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['cancel_expire' => 0]);
        UserMsgResult::add($user_id, [
            'title' => '注销账号通知',
            'content' => '账号：<b style="color:red">' . $myInfo['account'] . '</b>已经取消注销，可以正常使用。',
            'type' => 1
        ]);
        return $res ? $this->success_return('操作成功') : $this->error_return('操作失败');
    }

    ////不能是连续的6位数和倒序的6位数，和相同的6字符
    private function check_password($password)
    {
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        } elseif (mb_strlen($password) < 6) {
            return $this->error_return('密码长度不能小于6位');
        } elseif (mb_strlen($password) > 20) {
            return $this->error_return('密码长度不能大于20位');
        }
        if (in_array($password, ['123456', '654321', '123321', '321123', '888888', '111111', '000000'])) {
            return $this->error_return('密码太不安全了，请重新设置');
        }
        return self::success_return('密码格式正确');
    }

    //修改账号登录密码
    public function update_password($user_id, $arg): array
    {
        if (empty($arg['encryptedData']) || empty($arg['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($arg['encryptedData'], config('tools.encode.key'), $arg['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $arg = json_decode($res, true);
        $password = $arg['password'] ?? '';
        if (empty($password)) {
            return $this->error_return('请输入原密码');
        }
        if (empty($arg['new_password'])) {
            return $this->error_return('请输入新密码');
        }
        $new_password = trim($arg['new_password']);
        if (empty($arg['new_password_confirm'])) {
            return $this->error_return('请再次输入新密码');
        }
        if ($new_password <> $arg['new_password_confirm']) {
            return $this->error_return('两次输入的密码不一致');
        }

        $check_password = $this->check_password($new_password);
        if ($check_password['code'] <> 0) {
            return $check_password;
        }

        $myInfo = (new User())->data_get(['user_id' => $user_id], 'account,account_edit_time,salt,password');

        if (md5($password . $myInfo['salt']) <> $myInfo['password']) {
            return $this->error_return('原密码错误');
        }
        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($new_password . $salt);
        $up = [
            'password' => $password,
            'salt' => $salt,
        ];

        $res = (new User())->data_update(['user_id' => $user_id], $up);
        UserMsgResult::add($user_id, [
            'title' => '登录密码修改通知',
            'content' => '您的登录账号已修改，请使用新密码进行登录，请牢记新密码，请勿泄露给别人。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('修改失败');
    }

    //更新邮箱
    public function update_email($user_id, $arg): array
    {
        $email = $arg['email'] ?? '';
        $code = $arg['code'] ?? '';
        if (empty($email)) {
            return $this->error_return('邮箱不能为空');
        } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            return $this->error_return('邮箱格式不正确');
        } elseif (mb_strlen($email) > 60) {
            return $this->error_return('邮箱长度不能超过60个字符');
        } elseif (empty($code)) {
            return $this->error_return('验证码不能为空');
        }
        $user = (new User())->data_get(['email' => $email], 'user_id');
        if ($user && $user['user_id'] != $user_id) {
            return $this->error_return('邮箱已被其他账户使用');
        }
        $code = (new CodeResult())->check_code($email, $code);
        if ($code['code'] <> 0) {
            return $code;
        }
        $res = (new User())->data_update(['user_id' => $user_id], ['email' => $email]);
        UserMsgResult::add($user_id, [
            'title' => '邮箱修改通知',
            'content' => '您的邮箱已修改为：<b style="color:red">' . $email . '</b>，请使用新邮箱接收数据,邮箱也可以用于找回密码、登录等操作。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('邮箱未修改');
    }

    //关联账号列表
    public function account_list($user_id, $arg = []): array
    {
        $modelUser = new User;
        $relation_id = $this->get_relation_id($user_id);
        $account_list = $modelUser->data_list_nopage(['relation_id' => $relation_id], 'user_id,relation_id,user_code,account,username,avatar');
        if ($account_list) {
            foreach ($account_list as &$v) {
                $v['is_active'] = $v['user_id'] == $user_id ? 1 : 0;
                if (!$v['avatar']) {
                    $v['avatar'] = request()->domain(false) . '/static/image/default_image.png';
                }
                unset($v['user_id']);
            }
            unset($v);
        }
        return $this->success_return('获取成功', $account_list);
    }

    private function get_relation_id($user_id): int
    {
        $modelUser = new User;
        $relation_id = $modelUser->get_value(['user_id' => $user_id], 'relation_id');
        if (empty($relation_id)) {
            $relation_id = rand(10000000, 99999999);
            while (true) {
                $check = $modelUser->get_value(['relation_id' => $relation_id], 'user_id');
                if (!$check) {
                    break;
                }
                $relation_id = rand(10000000, 99999999);
            }
            $modelUser->data_update(['user_id' => $user_id], ['relation_id' => $relation_id]);
        }
        return $relation_id;
    }

    //关联账号
    public function account_bind($user_id, $args): array
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);

        $account = $args['account'] ?? '';
        $password = $args['password'] ?? '';
        if (empty($account)) {
            return $this->error_return('账号不能为空');
        }
        if (empty($password)) {
            return $this->error_return('密码不能为空');
        }
        $modelUser = new User;
        $relation_id = $this->get_relation_id($user_id);
        $user = $modelUser->data_get(['account' => $account], 'user_id,relation_id');
        if (!$user) {
            return $this->error_return('账号不存在');
        }
        if ($user['relation_id'] == $relation_id) {
            return $this->error_return('账号已关联');
        }
        if (!empty($user['relation_id']) && $user['relation_id'] != $relation_id) {
            $myRelationCount = $modelUser->data_count(['relation_id' => $relation_id]);
            if ($myRelationCount >= 2) {
                return $this->error_return('账号已关联到其他账户');
            }
            //我没关联其它账户，则关联到对应的账号下面
            $res = (new User())->data_update(['user_id' => $user_id], ['relation_id' => $user['relation_id']]);
            return $res ? $this->success_return('关联成功') : $this->error_return('关联失败');
        }
        $res = (new User())->data_update(['user_id' => $user['user_id']], ['relation_id' => $relation_id]);
        return $res ? $this->success_return('关联成功') : $this->error_return('关联失败');
    }

    //切换账号
    public function account_switch($user_id, $arg, $token): array
    {
        $account = $arg['account'] ?? '';
        if (empty($account)) {
            return $this->error_return('账号不能为空');
        }
        $modelUser = new User;
        $user = $modelUser->data_get(['account' => $account], 'user_id,relation_id,user_code');
        if (!$user) {
            return $this->error_return('账号不存在');
        } elseif ($user['user_id'] == $user_id) {
            return $this->error_return('不能切换到自己');
        }
        $relation_id = $this->get_relation_id($user_id);
        if ($user['relation_id'] != $relation_id) {
            return $this->error_return('账号未关联');
        }
        $res = $this->add_user_log($user['user_id'], 1);
        if (!$res) {
            return $this->error_return('切换失败');
        }
        cache($token, null);//清除token
        $token = $this->set_token($user['user_code']);
        return $this->success_return('切换成功', ['token' => $token]);
    }

    //解除关联
    public function account_unbind($user_id, $arg = []): array
    {
        $account = $arg['account'] ?? '';
        if (empty($account)) {
            return $this->error_return('账号不能为空');
        }
        $modelUser = new User;
        $user = $modelUser->data_get(['account' => $account], 'user_id,relation_id');
        if (!$user) {
            return $this->error_return('账号不存在');
        } elseif ($user['user_id'] == $user_id) {
            return $this->error_return('不能解除自己');
        }
        $relation_id = $this->get_relation_id($user_id);
        if ($user['relation_id'] != $relation_id) {
            return $this->error_return('账号未关联');
        }
        $res = (new User())->data_update(['user_id' => $user['user_id']], ['relation_id' => 0]);
        return $res ? $this->success_return('解除关联成功') : $this->error_return('解除关联失败');
    }


    //忘记密码
    public function forget_password($args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['email'] ?? "");
        $code = trim($args['code'] ?? "");
        $password = trim($args['password'] ?? "");
        if (empty($account)) {
            return $this->error_return('请输入绑定的邮箱');
        }
        if (empty($code)) {
            return $this->error_return('请输入验证码');
        }
        if (empty($password)) {
            return $this->error_return('请输入新密码');
        }
        //判断密码不可以小于6位，大于16位
        if (strlen($password) < 6 || strlen($password) > 16) {
            return $this->error_return('密码长度仅限6-16位');
        }
        //密码只能是数字、字母、下划线
        if (!preg_match('/^[0-9a-zA-Z_]+$/', $password)) {
            return $this->error_return('密码只能是数字、字母、下划线');
        }
        $checkCode = (new CodeResult())->check_code($account, $code, 3);
        if ($checkCode['code'] <> 0) {
            return $checkCode;
        }

        $myInfo = (new User())->data_get(['email' => $account], 'user_id,account,account_edit_time,salt,password');
        if (!$myInfo) {
            return $this->error_return('账号不存在');
        }

        $salt = substr(md5(uniqid('', true)), 0, 10);
        $password = md5($password . $salt);
        $up = [
            'password' => $password,
            'salt' => $salt,
        ];
        $res = (new User())->data_update(['user_id' => $myInfo['user_id']], $up);
        UserMsgResult::add($myInfo['user_id'], [
            'title' => '登录密码修改通知',
            'content' => '您的登录账号已修改，请使用新密码进行登录，请牢记新密码，请勿泄露给别人。',
            'type' => 1
        ]);
        return $res ? $this->success_return('修改成功') : $this->error_return('修改失败');
    }

    //忘记密码-验证码
    public function forget_code($args)
    {
        if (empty($args['encryptedData']) || empty($args['iv'])) {
            return $this->error_return('参数错误');
        }
        $res = ToolsResult::decrypt($args['encryptedData'], config('tools.encode.key'), $args['iv']);
        if (!$res) {
            return $this->error_return('参数非法');
        }
        $args = json_decode($res, true);
        $account = trim($args['email'] ?? "");
        $captcha_code = trim($args['captcha_code'] ?? "");
        $captcha_key = trim($args['captcha_key'] ?? "");
        if (empty($account)) {
            return $this->error_return('请输入绑定的邮箱');
        }
        if (empty($captcha_code) || empty($captcha_key)) {
            return $this->error_return('图形验证码不能为空');
        }
        if (!(new CodeResult())->captcha_check($captcha_key, $captcha_code)) {
            return $this->error_return('图形验证码错误');
        }
        $modelUser = new User;
        $user = $modelUser->data_get(['email' => $account], 'user_id');
        if (!$user) {
            return $this->error_return('邮箱不存在');
        }
        $res = (new CodeResult())->send_code($account, 3);
        return $res;
    }
}
